package com.yytek.nmp.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSON;
import com.yytek.common.client.base.MqMessage;
import com.yytek.common.core.constant.CacheConstants;
import com.yytek.common.core.domain.*;
import com.yytek.common.redis.service.RedisService;
import com.yytek.common.web.domain.ProCommonMessage;
import com.yytek.common.web.domain.ThingModelMessage;
import com.yytek.nmp.api.RemoteUpgradeService;
import com.yytek.nmp.api.domain.UpgradeHistory;
import com.yytek.nmp.domain.IotDeviceInfo;
import com.yytek.nmp.dto.DeviceStateCache;
import com.yytek.nmp.mapper.IotDeviceInfoMapper;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
@Slf4j
public class IotDeviceStateServiceImpl {
    @Autowired
    private RedisService redisService;
    @Autowired
    private IotDeviceInfoServiceImpl deviceInfoService;
    @Autowired
    private IotDeviceTaskServiceImpl deviceTaskService;
    @Autowired
    private RemoteUpgradeService remoteUpgradeService;
    @Autowired
    private IotDeviceInfoMapper iotDeviceInfoMapper;
    //设备超时分钟时间
    @Value("${scheduling.deviceStateOverdueMinute}")
    Integer deviceStateOverdueMinute;

    /**
     * 异步处理消息的设备状态业务信息
     * @param mqMsg
     */
    @Async("threadPoolExecutor")
    @Transactional(rollbackFor = Exception.class)
    public void changeDeviceStatusByMsg(MqMessage mqMsg) {
        String msg = new String(mqMsg.getPayload());
        //解析line中换成接收的参数实体
        ThingModelMessage thingModelMessage= JSON.parseObject
                (msg,ThingModelMessage.class);
        if(CollectionUtil.isNotEmpty(thingModelMessage.getData())){
            //上线设备启用 除了 状态的所有设备任务,更新数据库状态
            //下线设备禁用 除了 状态的所有设备任务,更新数据库状态
            List<ProCommonMessage> list = thingModelMessage.getData();

            Date current = new Date();
            for (int i = 0; i < list.size(); i++) {
                ProCommonMessage commonMessage = list.get(i);
                String iotId = commonMessage.getDeviceId();
                //(1-未激活 2-在线 3-离线))
                String status = commonMessage.getParams().get("connect_status").getValue();
                //采集设备状态缓存
                DeviceStateCache deviceStateCache = new DeviceStateCache();
                deviceStateCache.setIotId(iotId);
                deviceStateCache.setConnectStatus(Integer.valueOf(status));
                deviceStateCache.setLastConnectTime(current);
                //放入 采集设备状态 缓存,后续定时任务处理
                redisService.setCacheQueue(CacheConstants.DEVICE_STATE_HANDLE,deviceStateCache);
            }

        }
    }


    /**
     * 设备状态超时处理任务
     */
    public void deviceStateOverdue() {
        //获取所有设备key
        Set<String> keys = redisService.getLikeKey(CacheConstants.DEVICE_USEINFO_KEY);
        if(keys != null && keys.size() > 0){
            List<DeviceCache> changeList = new ArrayList<>();
            for (String key : keys) {
                //查询到设备缓存
                DeviceCache deviceCache = (DeviceCache)redisService.getCacheObject(key);
                if(deviceCache != null){
                    //如果是在线状态,判断是否超时
                    if(deviceCache.getConnectStatus() == 2){
                        //获取设备最后更新时间
                        Date lastTime = deviceCache.getLastConnectTime();
                        //最后更新时间不为空
                        if(lastTime != null){
                            //超时过期时间
                            Date overTime = DateUtil.offsetMinute(lastTime,deviceStateOverdueMinute);
                            //判断当前时间是否超过过期时间
                            //超过过期时间,则设备超时
                            Date current = new Date();
                            if(current.getTime() >= overTime.getTime()){
                                //设备设置离线状态更新
                                deviceCache.setConnectStatus(3);
                                changeList.add(deviceCache);
                            }
                        }else{
                            //设备设置离线状态更新
                            deviceCache.setConnectStatus(3);
                            changeList.add(deviceCache);
                        }
                    }
                }
            }
            //更新设备状态业务
            changeDeviceStateList(changeList);
        }
    }

    /**
     * 批量更新设备采集状态
     */
    public void changeDeviceStateTask() {
        //存在更新状态队列
        if(redisService.hasKey(CacheConstants.DEVICE_STATE_HANDLE)){
            //获取采集队列数据
            List<DeviceStateCache> deviceStateCacheList =
                    redisService.getCacheList(CacheConstants.DEVICE_STATE_HANDLE);
            //循环队列数据,剔除重复采集和按最新时间替换
            Map<String,DeviceStateCache> deviceStateCacheMap = new HashMap<>(16);
            if(CollectionUtil.isNotEmpty(deviceStateCacheList)){
                for (int i = 0; i < deviceStateCacheList.size(); i++) {
                    //查询是否存在设备id key
                    DeviceStateCache deviceStateCache = deviceStateCacheList.get(i);
                    String key = deviceStateCache.getIotId();
                    if(deviceStateCacheMap.containsKey(key)){
                        //存在对比更新最新时间
                        DeviceStateCache oldState =  deviceStateCacheMap.get(key);
                        //如果map中更新时间小于新的则更新
                        if(oldState.getLastConnectTime().getTime()
                                < deviceStateCache.getLastConnectTime().getTime()){
                            deviceStateCacheMap.put(key,deviceStateCache);
                        }
                    }else{
                        //不存在则放入map
                        deviceStateCacheMap.put(key,deviceStateCache);
                    }
                }
                //清除采集状态队列
                redisService.deleteObject(CacheConstants.DEVICE_STATE_HANDLE);
            }
            List<DeviceCache> changeList = new ArrayList<>();
            //对比对应设备缓存
            for (Map.Entry<String,DeviceStateCache> entry : deviceStateCacheMap.entrySet()) {
                //获取设备id
                String id = entry.getKey();
                //采集设备状态
                DeviceStateCache deviceStateCache =  entry.getValue();
                //查询到设备缓存信息
                DeviceCache deviceCache = deviceInfoService.getDeviceCacheByIotId(id);
                //找出变化的设备状态
                if(deviceStateCache.getConnectStatus() != deviceCache.getConnectStatus()){
                    //设置变化的状态,并添加进变化队列
                    deviceCache.setConnectStatus(deviceStateCache.getConnectStatus());
                    deviceCache.setLastConnectTime(deviceStateCache.getLastConnectTime());
                    changeList.add(deviceCache);
                }else {
                    //没有变化但更新最后更新时间
                    deviceCache.setLastConnectTime(deviceStateCache.getLastConnectTime());
                    redisService.setCacheObject(CacheConstants.DEVICE_USEINFO_KEY+deviceCache.getIotId(),
                            deviceCache);
                }
            }
            //设备状态业务处理
            changeDeviceStateList(changeList);
        }
    }

    /**
     * 批量处理设备状态业务变更
     * @param changeList
     */
    public void changeDeviceStateList(List<DeviceCache> changeList) {
        if(CollectionUtil.isNotEmpty(changeList)){
            //更新设备缓存和数据库状态
            changeDeviceStatus(changeList);
            //更新设备任务
            deviceTaskService.changeDeviceTask(changeList);
            //发送设备 未执行 升级消息
            sendUpgradeMsgByIot(changeList);
        }
    }

    /**
     * 发送设备 未执行 记录的升级消息
     * @param deviceCacheList
     */
    private void sendUpgradeMsgByIot(List<DeviceCache> deviceCacheList) {
        //循环设备查询未执行记录
        for (int i = 0; i < deviceCacheList.size(); i++) {
            DeviceCache deviceCache = deviceCacheList.get(i);
            //设备状态(1-未激活 2-在线 3-离线)
            String deviceStatus = deviceCache.getConnectStatus().toString();
            //如果设备在线发送升级消息
            if(deviceStatus.equals("2")){
                //执行状态(0:未执行,1:执行中,2:成功,3:失败,4:超时,5:操作冲突)
                List<UpgradeHistory> upgradeHistoryList =
                        remoteUpgradeService.selectUpgradeHisByIotId(deviceCache.getIotId(),0).getData();
                if(CollectionUtil.isNotEmpty(upgradeHistoryList)){
                    for (int j = 0; j < upgradeHistoryList.size(); j++) {
                        UpgradeHistory upgradeHistory = upgradeHistoryList.get(j);
                        //通过记录发送升级消息
                        deviceInfoService.sendDeviceUpgradeMsg(deviceCache.getIotId(),upgradeHistory.getStrategyId().toString());
                    }
                }
            }
        }

    }


    /**
     * 更改设备状态
     * @param list
     */
    private void changeDeviceStatus(List<DeviceCache> list) {
        List<IotDeviceInfo> updateList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            DeviceCache deviceCache = list.get(i);
            String iotId = deviceCache.getIotId();
            //(1-未激活 2-在线 3-离线))
            String status = deviceCache.getConnectStatus().toString();
            IotDeviceInfo deviceInfo = new IotDeviceInfo();
            deviceInfo.setIotId(iotId);
            deviceInfo.setConnectStatus(Integer.valueOf(status));
            deviceInfo.setLastTime(deviceCache.getLastConnectTime());
            updateList.add(deviceInfo);
            //更新设备缓存
            deviceCache.setDataAnalysisDown(null);
            deviceCache.setDataAnalysisUp(null);
            redisService.setCacheObject(CacheConstants.DEVICE_USEINFO_KEY+iotId,deviceCache);
        }
        iotDeviceInfoMapper.updateIotDeviceInfoList(updateList);
    }

}
